<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
    <style>
      canvas {
        border: 1px solid black;
      }
    </style>
  </head>
  <body>
    <canvas id="expansionCanvas" width="600" height="600"></canvas>
    <script>
      //   正北角度转笛卡尔角度
      function northToCartesianAngle(northAngle) {
        // 将正北角度转换为笛卡尔角度
        let cartesianAngle = (90 - northAngle) % 360;

        // 如果结果是负数，则添加360以确保它在[0, 360)范围内
        if (cartesianAngle < 0) {
          cartesianAngle += 360;
        }
        // 需要结果以弧度表示，可以取消下面这行的注释
        // cartesianAngle = cartesianAngle * Math.PI / 180;

        return cartesianAngle;
      }

      //   正北角度转笛卡尔弧度
      function northToCartesianRadians(northAngle) {
        // 将正北角度转换为笛卡尔角度（度）
        let cartesianAngleDegrees = (90 - northAngle) % 360;
        // 如果结果是负数，则添加360以确保它在[0, 360)范围内
        if (cartesianAngleDegrees < 0) {
          cartesianAngleDegrees += 360;
        }
        // 将笛卡尔角度从度转换为弧度
        let cartesianAngleRadians = (cartesianAngleDegrees * Math.PI) / 180;

        return cartesianAngleRadians;
      }

      /*
          已知圆心1(r1,r2)、第一个内圆半径R1、起始角θ1、终止角θ2、两个以圆心1绘制的圆的环宽都为H，飞机运动轨迹外扩12.5%，（内外都可以扩张）
          注意：这里的θ是正北坐标系角度，比如正北方向是0°，顺时针为正增长。
          解：
          |α|= |θ1-动态的θ|
          弧长 L=πr|α|/180°
          向扩张的长度当动态角度为θ时，b=H+L*12.5% ，因为有向内、外扩张两种情况。b需要正负两个值，且b是一个随时变化的量，因为弧长L随圆角度增长
          动态扩张的半径=±b+2H+第一个内圆半径R1
          所求的正北坐标系扩张路线，用极坐标表示扩张路线每个点用(x,y)如下：
              x=r1+动态扩张的半径*sin(θ)
              y=r2+动态扩张的半径*cos(θ)

          根据以上可以按点绘制飞机两种运动轨迹

          ！！！注意：canvas坐标原点是左上角。y向下是正！
        */
      function calculateExpansionPath(r1, r2, R1, θ1, θ2, H) {
        // 确保θ1 < θ2 以便于计算，如果不满足条件则交换它们。
        if (θ1 > θ2) {
          let temp = θ1;
          θ1 = θ2;
          θ2 = temp;
        }
        // else if (θ1 === θ2) {
        //   console.log("起始角和终止角不能相等");
        // }

        // const α = Math.abs(θ1 - θ2);
        const internal_points = [];
        const external_points = [];
        const expansionRate = 0.125; // 12.5% 扩张率

        for (let θ = θ1; θ <= θ2; θ += 5) {
          // 增量可以调整以获得更精细或更粗略的结果
          let α = Math.abs(θ - θ1);
          let L = (Math.PI * R1 * α) / 180; // 弧长L基于R1而不是动态扩张的半径 这里L有问题。内扩半径应该R1，外扩应该是R1+H+H

          let b = H + L * expansionRate; // 扩张长度b

          // 计算内外扩张的两个动态半径
          let outerRadius = b + 2 * H + R1;
          //   const innerRadius = -(b + 2 * H + R1);
          let innerRadius = R1 - b;

          // 将角度转换为弧度，因为Math.sin和Math.cos使用的是弧度
          //   const radian = (θ * Math.PI) / 180;
          let radian = northToCartesianRadians(θ);

          // 计算外扩路线上的点
          const xOuter = r1 + outerRadius * Math.cos(radian);
          const yOuter = r2 + outerRadius * Math.sin(radian); //为什么是减，因为屏幕坐标左上角是原点，和直角坐标系的y轴是反的
          external_points.push({ x: xOuter, y: yOuter });

          // 计算内缩路线上的点
          const xInner = r1 + innerRadius * Math.cos(radian);
          const yInner = r2 + innerRadius * Math.sin(radian);
          internal_points.push({ x: xInner, y: yInner });
        }

        let linesObj = {
          internal_points: internal_points,
          external_points: external_points,
        };
        return linesObj;
      }
      let r1 = 300;
      let r2 = 300;
      let R1 = 150;
      let θ1 = 0;
      let θ2 = 270;
      let H = 20;
      const drawLines = calculateExpansionPath(r1, r2, R1, θ1, θ2, H); // 测试示例参数值，角度是正北系角度
      console.log(drawLines);
      //   console.log(drawLines.external_points, drawLines.internal_points);

      // 获取canvas上下文
      var canvas = document.getElementById("expansionCanvas");
      var ctx = canvas.getContext("2d");

      ctx.strokeStyle = "red";
      // 绘制内部点之间的线
      if (drawLines.internal_points.length >= 2) {
        ctx.beginPath();
        ctx.moveTo(drawLines.internal_points[0].x, drawLines.internal_points[0].y);
        for (var i = 1; i < drawLines.internal_points.length; i++) {
          ctx.lineTo(drawLines.internal_points[i].x, drawLines.internal_points[i].y);
        }
        ctx.stroke(); // 绘制路径
      }

      // 绘制外部点之间的线
      if (drawLines.external_points.length >= 2) {
        ctx.beginPath();
        ctx.moveTo(drawLines.external_points[0].x, drawLines.external_points[0].y);
        for (var i = 1; i < drawLines.external_points.length; i++) {
          ctx.lineTo(drawLines.external_points[i].x, drawLines.external_points[i].y);
        }
        ctx.stroke(); // 绘制路径
      }

      //   笛卡尔度数转为正北度数
      function eastDegreesToNorthDegrees(degrees) {
        return (450 - degrees) % 360;
      }

      rad1 = northToCartesianRadians(θ1);
      rad2 = northToCartesianRadians(θ2);
      //   绘制内部三个圆环
      ctx.strokeStyle = "green";
      //   ctx.beginPath();
      //   ctx.arc(r1, r2, R1, rad1, rad2, true); //这里是弧度，要把之前的角度转成弧度
      //   ctx.stroke();

      ctx.beginPath();
      ctx.arc(r1, r2, R1 + H, rad1, rad2, true);
      ctx.stroke();

      //   ctx.beginPath();
      //   ctx.arc(r1, r2, R1 + H + H, rad1, rad2, true);
      //   ctx.stroke();
    </script>
  </body>
</html>
